package serverController;

import model.assessment.*;
import model.hospital.*;
import model.user.*;
import net.passClass.PassData;
import net.passClass.PassPatient;
import util.StringMapper;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.TreeSet;

public class MainNavigator {
    public static PassData fromPath(String[] paths,String args){

        return switch (paths[0]) {
            case "user" -> fromUser(paths, args);
            case "hospital" -> fromHospital(paths, args);
            case "assessment" -> fromAssessment(paths, args);
            case "patient" -> fromPatient(paths, args);
            default -> printInvalidPath(paths);
        };
    }

    private static PassData fromPatient(String[] paths,String args){

        HashMap<String,String> map = StringMapper.toMap(args);

        Patient aPatient = new Patient(
                map.get("name"),
                map.get("sex"),
                map.containsKey("birthday")?
                        map.get("birthday").equals("0")?
                                null:
                                new Date(Long.parseLong(map.get("birthday")))
                        : null,
                map.get("idNumber"),
                map.get("tel"),
                map.get("emergencyContact"),
                map.get("emergencyTel"),
                map.get("uid"),
                map.get("doctorUID")
        );

        return switch (paths[1]) {
            case "add" -> PatientDB.getInstance().add(aPatient);
            case "update" -> PatientDB.getInstance().update(aPatient);
            case "delete" -> PatientDB.getInstance().delete(aPatient);
            case "get" -> PatientDB.getInstance().get(aPatient);
            case "test" -> PatientDB.getInstance().test(
                    map.get("uid"),
                    new Date(Long.parseLong(map.getOrDefault("time", "0"))),
                    map.get("templateUID"),
                    Integer.parseInt(map.get("mark"))
            );
            default -> printInvalidPath(paths);
        };
    }

    private static PassData fromAssessment(String[] paths,String args){

        return switch (paths[1]) {
            case "template" -> fromTemplate(paths,args);
            case "question" -> fromQuestion(paths,args);
            default -> printInvalidPath(paths);
        };
    }

    private static PassData fromQuestion(String[] paths,String args){

        HashMap<String,String> map = StringMapper.toMap(args);
        Question aQuestion = new Question(
                map.get("name"),
                map.get("type"),
                map.get("answers_0"),
                map.get("answers_1"),
                map.get("answers_2"),
                map.get("uid")
        );

        return switch (paths[2]) {
            case "add" -> QuestionDB.getInstance().add(aQuestion);
            case "update" -> QuestionDB.getInstance().update(aQuestion);
            case "delete" -> QuestionDB.getInstance().delete(aQuestion);
            case "get" -> QuestionDB.getInstance().get(aQuestion);
            default -> printInvalidPath(paths);
        };
    }

    private static PassData fromTemplate(String[] paths,String args){

        HashMap<String,String> map = StringMapper.toMap(args);
        ArrayList<String> questions = new ArrayList<>();
        questions.add(map.get("questionUID"));
        Template aTemplate = new Template(
                map.get("name"),
                map.get("type"),
                questions,
                map.get("uid")
        );

        return switch (paths[2]) {
            case "add" -> TemplateDB.getInstance().add(aTemplate);
            case "update" -> TemplateDB.getInstance().update(aTemplate);
            case "delete" -> TemplateDB.getInstance().delete(aTemplate);
            case "get" -> TemplateDB.getInstance().get(aTemplate);
            case "addQuestion" -> TemplateDB.getInstance().addQuestion(aTemplate,map.get("questionUID"));
            case "deleteQuestion" -> TemplateDB.getInstance().deleteQuestion(aTemplate,map.get("questionUID"));
            default ->  printInvalidPath(paths);
        };
    }

    private static PassData fromHospital(String[] paths,String args){
        HashMap<String,String> map = StringMapper.toMap(args);

        Location location = new Location(
                map.containsKey("buildingNumber")?
                        map.get("buildingNumber").equals("")?
                                0:
                                Integer.parseInt(map.get("buildingNumber"))
                        :0,
                map.containsKey("floorNumber")?
                        map.get("floorNumber").equals("")?
                                0:
                                Integer.parseInt(map.get("floorNumber"))
                        :0,
                map.containsKey("roomNumber")?
                        map.get("roomNumber").equals("")?
                                0:
                                Integer.parseInt(map.get("roomNumber"))
                        :0
        );
        EquipmentRequest aRequest = new EquipmentRequest(
                new Date(map.containsKey("check_out")?
                        Long.parseLong(map.get("check_out")):0),
                map.get("userUID")
        );

        Equipment aEquipment =map.containsKey("capacity")?
                map.get("capacity").equals("")?
                        null:
                        new Equipment(Integer.parseInt(map.get("capacity")))
                :null;
        TreeSet<Bed> beds =null;
        if(map.containsKey("bedNumber") && !map.get("bedNumber").equals("")){
            Bed aBed = new Bed(Integer.parseInt(map.get("bedNumber")));
            beds = new TreeSet<>();
            beds.add(aBed);
        }
        Room aRoom = new Room(map.get("name"), location, map.get("type"), map.get("note"), aEquipment, beds);
        PassData answer;
        System.out.println(map);
        switch (paths[1]) {
            case "building","floor" -> answer = fromBuilding(paths,aRoom);
            case "room" -> answer = fromRoom(paths,aRoom);
            case "bed" -> answer = fromBed(paths,args);
            case "equipment" -> {
                Equipment e = Room.get(aRoom).getData().get(0).getEquipment();
                if(e == null){
                    return new PassData(false,null,"设备不存在");
                }
                return e.request(aRequest);
            }
            case "get" -> answer = BuildingDB.getInstance().get();
            default -> answer = printInvalidPath(paths);
        }
        return answer;
    }

    private static PassData fromRoom(String[] paths,Room room){
        return switch (paths[2]) {
            case "add" -> BuildingDB.getInstance().add(room);
            case "delete" -> BuildingDB.getInstance().delete(room);
            case "get" -> Room.get(room);
            default -> printInvalidPath(paths);
        };
    }

    private static PassData fromBed(String[] paths,String args){
        HashMap<String,String> map = StringMapper.toMap(args);

        Location location = new Location(
                map.containsKey("buildingNumber")?
                        Integer.parseInt(map.get("buildingNumber")):0,
                map.containsKey("floorNumber")?
                        Integer.parseInt(map.get("floorNumber")):0,
                map.containsKey("roomNumber")?
                        Integer.parseInt(map.get("roomNumber")):0
        );
        Bed aBed = new Bed(Integer.parseInt(map.get("bedNumber")));
        TreeSet<Bed> beds = new TreeSet<>();
        beds.add(aBed);
        Room aRoom = new Room(null, location, null, null, null, beds);

        switch (paths[2]) {
            case "add" :
                return BuildingDB.getInstance().add(aRoom);
            case "delete" :
                return BuildingDB.getInstance().delete(aRoom);
            case "check_in":
                PassPatient patient = PatientDB.getInstance().get(new Patient(map.get("patientUID")));
                if(patient.getData()==null){
                    return patient;
                }
                //System.out.println(patient.getData().get(0));
                return Room.get(aRoom).getData(1).get(0).getBeds().ceiling(aBed)
                        .check_in(patient.getData().get(0));
            case "check_out":
                return Room.get(aRoom).getData(1).get(0).getBeds().ceiling(aBed)
                        .check_out();
            case "exchange":
                Location location2 = new Location(
                        map.containsKey("buildingNumber2")?
                                Integer.parseInt(map.get("buildingNumber2")):0,
                        map.containsKey("floorNumber2")?
                                Integer.parseInt(map.get("floorNumber2")):0,
                        map.containsKey("roomNumber2")?
                                Integer.parseInt(map.get("roomNumber2")):0
                );
                Bed aBed2 = new Bed(Integer.parseInt(map.get("bedNumber2")));
                TreeSet<Bed> beds2 = new TreeSet<>();
                beds2.add(aBed2);
                Room aRoom2 = new Room(null, location2, null, null, null, beds2);
                PatientDB.getInstance().get(new Patient(map.get("patientUID")));
                return Room.get(aRoom).getData(1).get(0).getBeds().ceiling(aBed)
                        .exchange(Room.get(aRoom2).getData(1).get(0).getBeds().ceiling(aBed2));
            default :
                return printInvalidPath(paths);
        }
    }

    private static PassData fromBuilding(String[] paths,Room room){
        System.out.println(room);
        return switch (paths[2]) {
            case "add" -> BuildingDB.getInstance().add(room);
            case "delete" -> BuildingDB.getInstance().delete(room);
            default -> printInvalidPath(paths);
        };
    }

    private static PassData fromUser(String[] paths,String args){
        HashMap<String,String> map = StringMapper.toMap(args);
        User aUser = new User(map.get("username"), map.get("password"));
        return switch (paths[1]) {
            case "login" -> User.login(aUser);
            case "staff" -> fromStaff(paths, args);
            default -> printInvalidPath(paths);
        };
    }
    private static PassData fromStaff(String[] paths,String args){
        HashMap<String,String> map = StringMapper.toMap(args);

        Staff aStaff = new Staff(
                map.get("username"),
                map.get("password"),
                map.get("name"),
                map.containsKey("title")?
                        Integer.parseInt(map.get("title")): -1,
                map.containsKey("birthday")?
                        (map.get("birthday").equals("0")?
                                null: new Date(Long.parseLong(map.get("birthday"))))
                        : null,
                map.get("specialty"),
                map.get("tel"),
                map.get("idNumber"),
                map.get("uid")
        );
        System.out.println(aStaff);
        return switch (paths[2]) {
            case "add" -> StaffDB.getInstance().add(aStaff);
            case "update" -> StaffDB.getInstance().update(aStaff);
            case "delete" -> StaffDB.getInstance().delete(aStaff);
            case "get" -> StaffDB.getInstance().get(aStaff);
            default -> printInvalidPath(paths);
        };
    }

    private static PassData printInvalidPath(String[] paths){
        System.out.println("Client请求路径为:");
        for (String s : paths) {
            System.out.print("/"+s);
        }
        System.out.println("\n请求路径非法");
        return new PassData(false,null,"请求路径非法");
    }
}
